package net.huashitong.ssydt.provider.money.service;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import net.huashitong.ssydt.exceptions.ServiceException;
import net.huashitong.ssydt.money.constant.MoneyConsts;
import net.huashitong.ssydt.money.entity.*;
import net.huashitong.ssydt.money.entity.vo.*;
import net.huashitong.ssydt.provider.alipay.service.AlipayService;
import net.huashitong.ssydt.provider.applepay.config.ApplePayConfig;
import net.huashitong.ssydt.provider.applepay.dto.IapVerifyDto;
import net.huashitong.ssydt.provider.security.exceptions.ParamErrorException;
import net.huashitong.ssydt.provider.sys.service.SsSysTableService;
import net.huashitong.ssydt.provider.utils.date.DateUtils;
import net.huashitong.ssydt.provider.wxpay.service.WeChatPayService;
import net.huashitong.ssydt.security.utils.ValidUtils;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author <a href="mailto:yhy23456@163.com">huiyang.yu</a>
 * @since 2017.08.14
 */
@Service
@Transactional
public class MoneyServiceImpl implements MoneyService {

    private static final String GOODS_TYPE_ERROR = "商品类型错误";

    private static final String ALREADY_PAY_ORDER = "您已支付该订单";

    private Logger logger = LoggerFactory.getLogger(MoneyServiceImpl.class);

    private SsMoneyVipBagService ssMoneyVipBagService;

    private SsMoneyGoldService ssMoneyGoldService;

    private SsMoneyGoldBagService ssMoneyGoldBagService;

    private SsSysTableService ssSysTableService;

    private SsMoneyOrderService ssMoneyOrderService;

    private SsMoneyOrderDetailService ssMoneyOrderDetailService;

    private SsMoneyVipRecordService ssMoneyVipRecordService;

    private SsMoneyGoldRecordService ssMoneyGoldRecordService;

    private WeChatPayService weChatPayService;

    private AlipayService alipayService;

    private SsMoneyVipService ssMoneyVipService;
    /**
     * 一天的毫秒数
     */
    private static final long DAY_MILLISECOND = 86400000L;

    private ApplePayConfig applePayConfig;


    @Autowired
    public MoneyServiceImpl(SsMoneyVipBagService ssMoneyVipBagService,
                            SsMoneyGoldService ssMoneyGoldService,
                            SsMoneyGoldBagService ssMoneyGoldBagService,
                            SsSysTableService ssSysTableService,
                            SsMoneyOrderService ssMoneyOrderService,
                            SsMoneyOrderDetailService ssMoneyOrderDetailService,
                            SsMoneyVipRecordService ssMoneyVipRecordService,
                            SsMoneyGoldRecordService ssMoneyGoldRecordService,
                            WeChatPayService weChatPayService,
                            AlipayService alipayService,
                            SsMoneyVipService ssMoneyVipService,
                            ApplePayConfig applePayConfig) {

        this.ssMoneyVipBagService = ssMoneyVipBagService;
        this.ssMoneyGoldService = ssMoneyGoldService;
        this.ssMoneyGoldBagService = ssMoneyGoldBagService;
        this.ssSysTableService = ssSysTableService;
        this.ssMoneyOrderService = ssMoneyOrderService;
        this.ssMoneyOrderDetailService = ssMoneyOrderDetailService;
        this.ssMoneyVipRecordService = ssMoneyVipRecordService;
        this.ssMoneyGoldRecordService = ssMoneyGoldRecordService;
        this.weChatPayService = weChatPayService;
        this.alipayService = alipayService;
        this.ssMoneyVipService = ssMoneyVipService;
        this.applePayConfig = applePayConfig;
    }

    @Override
    public List<VipBagsVo> vipBags() {
        List<SsMoneyVipBag> ssMoneyVipBags = ssMoneyVipBagService.queryByState();
        List<VipBagsVo> list = new ArrayList<>();
        for (SsMoneyVipBag ssMoneyVipBag : ssMoneyVipBags) {
            VipBagsVo vipBagsVo = new VipBagsVo(ssMoneyVipBag);
            list.add(vipBagsVo);
        }
        return list;
    }

    @Override
    public List<VipBagsVo> vipBagsByAppType(String appType) {
        List<SsMoneyVipBag> ssMoneyVipBags = ssMoneyVipBagService.queryByAppType(appType);
        List<VipBagsVo> list = new ArrayList<>();
        for (SsMoneyVipBag ssMoneyVipBag : ssMoneyVipBags) {
            VipBagsVo vipBagsVo = new VipBagsVo(ssMoneyVipBag);
            list.add(vipBagsVo);
        }
        return list;
    }

    @Override
    public GoldsMyVo goldsMy(String userId) {
        SsMoneyGold ssMoneyGold = ssMoneyGoldService.getByUserId(userId);
        if (ssMoneyGold == null) {
            throw new ServiceException("账户不存在");
        }
        return new GoldsMyVo(ssMoneyGold);
    }

    @Override
    public List<GoldyVo> golds() {
        List<SsMoneyGoldBag> ssMoneyGoldBags = ssMoneyGoldBagService.queryByState();
        List<GoldyVo> list = new ArrayList<>();
        for (SsMoneyGoldBag ssMoneyGoldBag : ssMoneyGoldBags) {
            GoldyVo goldyVo = new GoldyVo(ssMoneyGoldBag);
            list.add(goldyVo);
        }
        return list;
    }

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public OrderOutVO orders(OrderInVO orderInVO, String userId) {
        ValidUtils.validTerminal(orderInVO.getTerminal());//客户端类型校验
        //生产订单id
        String orderId = ssSysTableService.updateMaxId("t_ss_money_order");
        //生成商品
        List<OrderInVO.Goods> goodses = orderInVO.getGoodses();
        List<SsMoneyOrderDetail> ssMoneyOrderDetails = new ArrayList<>();
        for (OrderInVO.Goods goods : goodses) {
            //商品购买限制校验
            validGoodsLimit(goods, userId);
            SsMoneyOrderDetail ssMoneyOrderDetail = new SsMoneyOrderDetail();
            this.setUnitPriceAndGoodName(goods, ssMoneyOrderDetail);
            ssMoneyOrderDetail.setOrderId(orderId);
            ssMoneyOrderDetail.setGoodsId(goods.getGoodsId());
            ssMoneyOrderDetail.setNumber(goods.getNumber());
            ssMoneyOrderDetail.setGoodsType(goods.getGoodsType());
            ssMoneyOrderDetails.add(ssMoneyOrderDetail);
        }

        //生成订单
        SsMoneyOrder ssMoneyOrder = new SsMoneyOrder();
        ssMoneyOrder.setOrderId(orderId);
        ssMoneyOrder.setUserId(userId);
        this.setOrderPriceAndOrdrName(ssMoneyOrder, ssMoneyOrderDetails);
        ssMoneyOrder.setOrderState(MoneyConsts.OrderState.UNPAID);
        ssMoneyOrder.setPayAccount("");
        ssMoneyOrder.setTerminal(orderInVO.getTerminal());
        ssMoneyOrder.setDeviceCode(orderInVO.getDeviceCode());
        ssMoneyOrder.setDeviceType(orderInVO.getDeviceType());
        ssMoneyOrder.setDeviceOperation(orderInVO.getDeviceOperation());
        ssMoneyOrder.setClientVersion(orderInVO.getClientVersion());
        ssMoneyOrderService.save(ssMoneyOrder);//保存订单
        ssMoneyOrderDetailService.batchSave(ssMoneyOrderDetails);//批量保存商品

        return new OrderOutVO(ssMoneyOrder);
    }

    @Override
    public VipMyVO vipMy(String userId) {
        boolean isVip = false;
        Date gmtEnd = new Date(System.currentTimeMillis());
        SsMoneyVip ssMoneyVip = ssMoneyVipService.getByUserId(userId);
        if (ssMoneyVip != null) {
            //转成日期字符比较，只对天敏感
            String nowDateStr = DateUtils.formatDate(gmtEnd, "yyyyMMdd");
            String gmtEndStr = DateUtils.formatDate(ssMoneyVip.getGmtEnd(), "yyyyMMdd");
            if (nowDateStr.compareTo(gmtEndStr) <= 0) {
                isVip = true;
                gmtEnd = ssMoneyVip.getGmtEnd();
            }
        }
        VipMyVO vipMyVO = new VipMyVO();
        vipMyVO.setGmtEnd(gmtEnd);
        vipMyVO.setVip(isVip);
        return vipMyVO;
    }

    @Override
    public List<GoldsRecordsMyOutVO> goldsRecordsMy(GoldsRecordsMyInVO goldsRecordsMyInVO, String userId) {
        goldsRecordsMyInVO.setUserId(userId);
        boolean operation = "+".equals(goldsRecordsMyInVO.getOperation()) || "-".equals(goldsRecordsMyInVO.getOperation());
        if (!operation) {
            throw new ParamErrorException("操作值非法");
        }
        List<SsMoneyGoldRecord> ssMoneyGoldRecords = ssMoneyGoldRecordService.queryIdDescByUserId(goldsRecordsMyInVO);
        List<GoldsRecordsMyOutVO> list = new ArrayList<>();
        for (SsMoneyGoldRecord ssMoneyGoldRecord : ssMoneyGoldRecords) {
            GoldsRecordsMyOutVO goldsRecordsMyOutVO = new GoldsRecordsMyOutVO(ssMoneyGoldRecord);
            list.add(goldsRecordsMyOutVO);
        }
        return list;
    }

    @Override
    public TreeMap<String, String> wechatPay(String orderId, HttpServletRequest request) {
        SsMoneyOrder ssMoneyOrder = ssMoneyOrderService.getByOrderId(orderId);
        if (ssMoneyOrder == null) {
            throw new ServiceException("订单不存在");
        }

        //防止重复处理订单
        if (MoneyConsts.OrderState.PAID.equals(ssMoneyOrder.getOrderState())) {
            throw new ServiceException(ALREADY_PAY_ORDER);
        }

        return weChatPayService.unifiedOrderForApp(ssMoneyOrder, request);
    }

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void payCallback(SsMoneyOrder order) {
        SsMoneyOrder ssMoneyOrder = this.ssMoneyOrderService.getByOrderId(order.getOrderId());
        if (ssMoneyOrder == null) {
            throw new ServiceException(String.format("订单不存在，orderId: [%s]", order.getOrderId()));
        }
        List<SsMoneyOrderDetail> ssMoneyOrderDetails = ssMoneyOrderDetailService
                .queryByOrderId(ssMoneyOrder.getOrderId());
        if (ssMoneyOrderDetails == null || ssMoneyOrderDetails.isEmpty()) {
            throw new ServiceException(String.format("订单不存在在商品，orderId: [%s]", order.getOrderId()));
        }
        for (SsMoneyOrderDetail ssMoneyOrderDetail : ssMoneyOrderDetails) {
            switch (ssMoneyOrderDetail.getGoodsType()) {
                case MoneyConsts.GoodsType.VIP_BAG:
                    vipBagGoodsHandler(ssMoneyOrder, ssMoneyOrderDetail);
                    break;
                case MoneyConsts.GoodsType.GOLD_BAG:
                    goldBagGoodsHandler(ssMoneyOrder, ssMoneyOrderDetail);
                    break;
                case MoneyConsts.GoodsType.GOODS:
                    //暂时无普通商品
                    throw new ServiceException("暂时无普通商品");
                default:
                    throw new ServiceException(GOODS_TYPE_ERROR);
            }
        }
    }

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void goldPay(String orderId, String userId) {
        SsMoneyOrder ssMoneyOrder = this.ssMoneyOrderService.getByOrderId(orderId);
        if (ssMoneyOrder == null) {
            throw new ServiceException(String.format("订单不存在，orderId: [%s]", orderId));
        }
        //防止重复处理订单
        if (MoneyConsts.OrderState.PAID.equals(ssMoneyOrder.getOrderState())) {
            throw new ServiceException(ALREADY_PAY_ORDER);
        }
        SsMoneyGold ssMoneyGold = ssMoneyGoldService.getByUserId(ssMoneyOrder.getUserId());
        if (ssMoneyGold == null) {
            logger.error("用户的账户不存在, userId [{}]", ssMoneyOrder.getUserId());
            throw new ServiceException("用户的账户不存在");
        }
        //扣除金币
        long orderGoldNumber = ssMoneyOrder.getOrderPrice()
                .multiply(new BigDecimal(SsMoneyGold.GOLD_RATE)).longValue();
        long goldNumber = ssMoneyGold.getGoldNumber() - orderGoldNumber;
        if (goldNumber < 0) {
            throw new ServiceException("金币余额不足");
        }
        ssMoneyGold.setGoldNumber(goldNumber);
        ssMoneyGoldService.updateGoldNumberById(ssMoneyGold);
        //记录金币记录
        SsMoneyGoldRecord ssMoneyGoldRecord = new SsMoneyGoldRecord();
        ssMoneyGoldRecord.setUserId(ssMoneyOrder.getUserId());
        ssMoneyGoldRecord.setAccountId(ssMoneyGold.getId());
        ssMoneyGoldRecord.setOperation("-");
        ssMoneyGoldRecord.setGoldNumber(orderGoldNumber);
        ssMoneyGoldRecord.setRemainderMoney(ssMoneyGold.getGoldNumber());
        ssMoneyGoldRecord.setDescription("金币支付");
        ssMoneyGoldRecord.setOrderId(ssMoneyOrder.getOrderId());
        ssMoneyGoldRecordService.save(ssMoneyGoldRecord);

        //修改订单状态
        ssMoneyOrder.setPayType(MoneyConsts.PayType.GOLD_PAY);
        ssMoneyOrder.setPayAccount(String.valueOf(ssMoneyGold.getId()));
        ssMoneyOrder.setPayOrderId(orderId);
        ssMoneyOrder.setGmtPay(new Date(System.currentTimeMillis()));
        ssMoneyOrder.setOrderState(MoneyConsts.OrderState.PAID);
        ssMoneyOrderService.update(ssMoneyOrder);
        //执行回调
        this.payCallback(ssMoneyOrder);
    }

    @Override
    public String alipayPay(String orderId) {
        SsMoneyOrder ssMoneyOrder = ssMoneyOrderService.getByOrderId(orderId);
        if (ssMoneyOrder == null) {
            throw new ServiceException("订单不存在");
        }
        //防止重复处理订单
        if (MoneyConsts.OrderState.PAID.equals(ssMoneyOrder.getOrderState())) {
            throw new ServiceException(ALREADY_PAY_ORDER);
        }

        return alipayService.orderForApp(ssMoneyOrder);
    }

    @Override
    public void applePay(ApplePayVO applePayVO, String userId) throws IOException {
        SsMoneyOrder ssMoneyOrder = ssMoneyOrderService.getByOrderId(applePayVO.getOrderId());
        //订单不存在
        if (ssMoneyOrder == null) {
            throw new ServiceException("订单不存在");
        }

        //防止重复处理订单
        if (MoneyConsts.OrderState.PAID.equals(ssMoneyOrder.getOrderState())) {
            return;
//            throw new ServiceException(ALREADY_PAY_ORDER);
        }

        if (!ssMoneyOrder.getUserId().equals(userId)) {
            throw new ServiceException("非法操作");
        }

        //根据不同的环境，选择是去测试环境还是开发环境验证
        String verifyUri = applePayConfig.isProd() ? applePayConfig.getIapProdVerifyUri() : applePayConfig.getIapSendboxVerifyUri();
        JsonObject obj = new JsonObject();
        obj.addProperty("receipt-data", applePayVO.getReceiptData());
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), obj.toString());
        Request request = new Request.Builder().url(verifyUri).post(body).build();
        execute(request, body, ssMoneyOrder);
    }

    private void execute(Request request, RequestBody body, SsMoneyOrder ssMoneyOrder) throws IOException {
        try {
            Response response = new OkHttpClient().newCall(request).execute();
            if (response.isSuccessful()) {
                String result = response.body().string();
                //解析json
                IapVerifyDto iapVerifyDto = new Gson().fromJson(new JsonParser().parse(result),
                        new TypeToken<IapVerifyDto>() {
                        }.getType());

                if (iapVerifyDto.getStatus() == 0) {
                    //下面是伪代码，说下处理思路
                    //判断product_id，看返回的product_id与实际的充值金额是不是一致，防止骗单
                    //将订单更改为成功
                    String productId;
                    if (iapVerifyDto.getReceipt().getIn_app() == null || iapVerifyDto.getReceipt().getIn_app().size() == 0) {
                        productId = iapVerifyDto.getReceipt().getProduct_id();
                    } else {
                        productId = iapVerifyDto.getReceipt().getIn_app().get(0).getProduct_id();
                    }

                    ssMoneyOrder.setPayType(MoneyConsts.PayType.APPLE_PAY);
//                    ssMoneyOrder.setPayAccount();
                    ssMoneyOrder.setPayOrderId(productId);
                    ssMoneyOrder.setGmtPay(new Date(System.currentTimeMillis()));
                    ssMoneyOrder.setOrderState(MoneyConsts.OrderState.PAID);
                    ssMoneyOrderService.update(ssMoneyOrder);
                    payCallback(ssMoneyOrder);//支付回调


                } else if (iapVerifyDto.getStatus() == 21007) {
                    //下面是伪代码，说下处理思路
                    //验证sandbox环境，主要就是为了appstore审核
                    request = new Request.Builder().url(applePayConfig.getIapSendboxVerifyUri()).post(body).build();
                    execute(request, body, ssMoneyOrder);
                } else {
                    //记录错误日志
                    throw new ServiceException("验证失败，code:" + iapVerifyDto.getStatus());
                }
            } else {
                //记录错误日志
                throw new ServiceException("验证失败,网络无响应");
            }
        } catch (JsonSyntaxException e) {
            //记录错误日志
            throw new ServiceException("验证失败，JSON解析失败");
        }
    }

    /**
     * 处理购买金币套餐
     *
     * @param ssMoneyOrder
     * @param ssMoneyOrderDetail
     */
    private void goldBagGoodsHandler(SsMoneyOrder ssMoneyOrder, SsMoneyOrderDetail ssMoneyOrderDetail) {
        //修改用户金币的额度
        SsMoneyGoldBag ssMoneyGoldBag = ssMoneyGoldBagService.getById(ssMoneyOrderDetail.getGoodsId());
        if (ssMoneyGoldBag == null) {
            logger.error("金币套餐包不存在，订单号[{}]，订单明细号[{}]",
                    ssMoneyOrder.getOrderId(), ssMoneyOrderDetail.getId());
            throw new ServiceException("金币套餐包不存在");
        }
        SsMoneyGold ssMoneyGold = ssMoneyGoldService.getByUserId(ssMoneyOrder.getUserId());
        if (ssMoneyGold == null) {
            logger.error("用户的账户不存在, userId [{}]", ssMoneyOrder.getUserId());
            throw new ServiceException("用户的账户不存在");
        }
        long addGoldNumber = ssMoneyGoldBag.getGoldNumber() * (long) ssMoneyOrderDetail.getNumber();
        ssMoneyGold.setGoldNumber(ssMoneyGold.getGoldNumber() + addGoldNumber);
        ssMoneyGoldService.updateGoldNumberById(ssMoneyGold);

        //记录金币记录
        String description;
        switch (ssMoneyOrder.getPayType()) {
            case MoneyConsts.PayType.WE_CHAT_PAY:
                description = "微信支付充值";
                break;
            case MoneyConsts.PayType.ALI_PAY:
                description = "支付宝支付充值";
                break;
            case MoneyConsts.PayType.APPLE_PAY:
                description = "苹果支付充值";
                break;
            default:
                description = "充值";
        }
        SsMoneyGoldRecord ssMoneyGoldRecord = new SsMoneyGoldRecord();
        ssMoneyGoldRecord.setUserId(ssMoneyOrder.getUserId());
        ssMoneyGoldRecord.setAccountId(ssMoneyGold.getId());
        ssMoneyGoldRecord.setOperation("+");
        ssMoneyGoldRecord.setGoldNumber(addGoldNumber);
        ssMoneyGoldRecord.setRemainderMoney(ssMoneyGold.getGoldNumber());
        ssMoneyGoldRecord.setDescription(description);
        ssMoneyGoldRecord.setOrderId(ssMoneyOrder.getOrderId());
        ssMoneyGoldRecordService.save(ssMoneyGoldRecord);

    }

    /**
     * 处理购买vip套餐包
     *
     * @param ssMoneyOrder
     * @param ssMoneyOrderDetail
     */
    private void vipBagGoodsHandler(SsMoneyOrder ssMoneyOrder, SsMoneyOrderDetail ssMoneyOrderDetail) {
        SsMoneyVipBag ssMoneyVipBag = ssMoneyVipBagService.getById(ssMoneyOrderDetail.getGoodsId());
        if (ssMoneyVipBag == null) {
            logger.error("vip套餐包不存在，订单号[{}]，订单明细号[{}]",
                    ssMoneyOrder.getOrderId(), ssMoneyOrderDetail.getId());
            throw new ServiceException("vip套餐包不存在");
        }

        Date nowDate = new Date(System.currentTimeMillis());
        Date recordGmtStart = nowDate;
        VipMyVO vipMyVO = vipMy(ssMoneyOrder.getUserId());
        if (vipMyVO.isVip()) {
            recordGmtStart = vipMyVO.getGmtEnd();
        }
        Map<String, Object> map = getGmtEndAndEffectiveDay(recordGmtStart, ssMoneyVipBag, ssMoneyOrderDetail);
        Date vipGmtEnd = (Date) map.get("gmtEnd");
        //变更vip信息
        SsMoneyVip ssMoneyVip = ssMoneyVipService.getByUserId(ssMoneyOrder.getUserId());
        if (ssMoneyVip == null) {
            ssMoneyVip = new SsMoneyVip();
            ssMoneyVip.setUserId(ssMoneyOrder.getUserId());
            ssMoneyVip.setGmtStart(nowDate);
            ssMoneyVip.setGmtEnd(vipGmtEnd);
            ssMoneyVipService.save(ssMoneyVip);
        } else {
            if (!vipMyVO.isVip()) {
                ssMoneyVip.setGmtStart(nowDate);
            }
            ssMoneyVip.setGmtEnd(vipGmtEnd);
            ssMoneyVipService.updateSelective(ssMoneyVip);
        }

        //保存vip开通记录
        SsMoneyVipRecord ssMoneyVipRecord = new SsMoneyVipRecord();
        ssMoneyVipRecord.setUserId(ssMoneyOrder.getUserId());
        ssMoneyVipRecord.setVipBagId(ssMoneyVipBag.getId());
        ssMoneyVipRecord.setGmtStart(recordGmtStart);
        ssMoneyVipRecord.setGmtEnd(vipGmtEnd);
        ssMoneyVipRecord.setGmtBuy(nowDate);
        ssMoneyVipRecord.setOrderId(ssMoneyOrder.getOrderId());
        ssMoneyVipRecord.setRemarks("");
        ssMoneyVipRecord.setEffectiveDay((Integer) map.get("effectiveDay"));
        ssMoneyVipRecordService.save(ssMoneyVipRecord);
    }

    /**
     * 获取vip到期时间和有效天数
     *
     * @param recordGmtStart     vip记录的开始时间
     * @param ssMoneyVipBag
     * @param ssMoneyOrderDetail
     * @return
     */
    private Map<String, Object> getGmtEndAndEffectiveDay(Date recordGmtStart,
                                                         SsMoneyVipBag ssMoneyVipBag, SsMoneyOrderDetail ssMoneyOrderDetail) {
        Date gmtEnd = new Date(System.currentTimeMillis());
        Integer effectiveDay = 0;
        switch (ssMoneyVipBag.getBagType()) {
            case MoneyConsts.BagType.EFFECTIVE_DAYS:
                effectiveDay = ssMoneyVipBag.getBagDay() * ssMoneyOrderDetail.getNumber();
                long millisecond = DAY_MILLISECOND * effectiveDay;
                gmtEnd = new Date(recordGmtStart.getTime() + millisecond);
                break;
            case MoneyConsts.BagType.DEADLINE:
                long time = ssMoneyVipBag.getGmtExpiryDate().getTime() - System.currentTimeMillis();
                if (time > 0 && time <= DAY_MILLISECOND) {
                    effectiveDay = 1;
                    gmtEnd = new Date(recordGmtStart.getTime() + DAY_MILLISECOND);
                } else if (time > DAY_MILLISECOND) {
                    long dayTemp = (time / DAY_MILLISECOND);
                    effectiveDay = (int) ((time % DAY_MILLISECOND == 0) ? dayTemp : (dayTemp + 1));
                    gmtEnd = new Date(recordGmtStart.getTime() + (DAY_MILLISECOND * effectiveDay));
                }
                break;
            default:
                throw new ServiceException("vip套餐包，套餐类型错误");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("gmtEnd", gmtEnd);
        map.put("effectiveDay", effectiveDay);
        return map;
    }

    /**
     * 设置订单价格(总价保留2位小数，多余位数直接舍去)，
     * 设置订单名称
     *
     * @param ssMoneyOrder
     * @param ssMoneyOrderDetails
     */
    private void setOrderPriceAndOrdrName(SsMoneyOrder ssMoneyOrder, List<SsMoneyOrderDetail> ssMoneyOrderDetails) {
        BigDecimal totalPrice = new BigDecimal(0);
        List<String> orderNames = new ArrayList<>();
        for (SsMoneyOrderDetail ssMoneyOrderDetail : ssMoneyOrderDetails) {
            BigDecimal number = new BigDecimal(ssMoneyOrderDetail.getNumber());
            BigDecimal goodsPrice = ssMoneyOrderDetail.getUnitPrice().multiply(number);
            totalPrice = totalPrice.add(goodsPrice);
            orderNames.add(ssMoneyOrderDetail.getGoodsName());
        }
        String orderName;
        if (orderNames.size() > 1) {
            orderName = String.format("%s等商品", orderNames.get(0));
        } else {
            orderName = orderNames.get(0);
        }
        ssMoneyOrder.setOrderName(orderName);
        ssMoneyOrder.setOrderPrice(totalPrice.setScale(2, BigDecimal.ROUND_DOWN));
    }

    /**
     * 设置单价和商品价格
     *
     * @param goods
     * @param ssMoneyOrderDetail
     */
    private void setUnitPriceAndGoodName(OrderInVO.Goods goods, SsMoneyOrderDetail ssMoneyOrderDetail) {
        BigDecimal unitPrice = null;
        String goodsName = null;
        //判断商品类型，根据类型取商品信息
        switch (goods.getGoodsType()) {
            case MoneyConsts.GoodsType.VIP_BAG:
                SsMoneyVipBag ssMoneyVipBag = ssMoneyVipBagService.getById(goods.getGoodsId());
                unitPrice = this.getGoodsPrice(ssMoneyVipBag);
                goodsName = ssMoneyVipBag.getBagName();
                break;
            case MoneyConsts.GoodsType.GOLD_BAG:
                SsMoneyGoldBag ssMoneyGoldBag = ssMoneyGoldBagService.getById(goods.getGoodsId());
                unitPrice = this.getGoodsPrice(ssMoneyGoldBag);
                goodsName = ssMoneyGoldBag.getBagName();
                break;
            case MoneyConsts.GoodsType.GOODS:
                //暂时无普通商品
                throw new ServiceException(GOODS_TYPE_ERROR);
            default:
                throw new ServiceException(GOODS_TYPE_ERROR);
        }
        ssMoneyOrderDetail.setUnitPrice(unitPrice);
        ssMoneyOrderDetail.setGoodsName(goodsName);
    }

    /**
     * 获取商品价格
     *
     * @param basePriceEntity
     * @return
     */
    private BigDecimal getGoodsPrice(BasePriceEntity basePriceEntity) {
        BigDecimal price;
        switch (basePriceEntity.getNowExecute()) {
            case MoneyConsts.NowExecute.ORIGINA_PRICE:
                price = basePriceEntity.getOriginalPrice();
                break;
            case MoneyConsts.NowExecute.FAVOURABLE_PRICE:
                price = basePriceEntity.getFavourablePrice();
                break;
            case MoneyConsts.NowExecute.PREFERENCE_PRICE:
                price = basePriceEntity.getPreferencePrice();
                break;
            default:
                price = basePriceEntity.getOriginalPrice();
                break;
        }
        return price;
    }


    /**
     * 购买次数限制处理
     *
     * @param goods  OrderInVO.Goods 商品对象
     * @param userId
     */
    private void validGoodsLimit(OrderInVO.Goods goods, String userId) {
        switch (goods.getGoodsType()) {
            case MoneyConsts.GoodsType.VIP_BAG:
                validVipBagNumberLimit(goods, userId);
                break;
            case MoneyConsts.GoodsType.GOLD_BAG:
                validGoldBagNumberLimit(goods, userId);
                break;
            case MoneyConsts.GoodsType.GOODS:
                //暂时无普通商品
                throw new ServiceException("暂时无普通商品");
            default:
                throw new ServiceException(GOODS_TYPE_ERROR);
        }

    }

    /**
     * VIP购买次数限制
     *
     * @param goods
     * @param userId
     */
    private void validVipBagNumberLimit(OrderInVO.Goods goods, String userId) {
        SsMoneyVipBag ssMoneyVipBag = ssMoneyVipBagService.getById(goods.getGoodsId());
        if (ssMoneyVipBag == null) {
            throw new ServiceException(String.format("VIP套餐不存在，id [%d]", goods.getGoodsId()));
        }
        if (ssMoneyVipBag.getNumberLimit() > 0) {
            validNumberLimit(userId, goods, ssMoneyVipBag.getNumberLimit());
        }
    }


    /**
     * 金币购次数限制
     *
     * @param goods
     * @param userId
     */
    private void validGoldBagNumberLimit(OrderInVO.Goods goods, String userId) {
        SsMoneyGoldBag ssMoneyGoldBag = ssMoneyGoldBagService.getById(goods.getGoodsId());
        if (ssMoneyGoldBag == null) {
            throw new ServiceException(String.format("金币套餐不存在，id [%d]", goods.getGoodsId()));
        }
        if (ssMoneyGoldBag.getNumberLimit() > 0) {
            validNumberLimit(userId, goods, ssMoneyGoldBag.getNumberLimit());
        }
    }

    /**
     * 次数检验
     *
     * @param userId
     * @param goods
     * @param numberLimit
     */
    private void validNumberLimit(String userId, OrderInVO.Goods goods, int numberLimit) {
        boolean isBig = goods.getNumber() > numberLimit;
        if (isBig) {
            throw new ServiceException("下单失败，原因：超过购买次数限制。");
        } else {
            List<SsMoneyOrderDetail> ssMoneyOrderDetails = ssMoneyOrderDetailService
                    .queryJoinOrderByUserIdWithGoodsIdWithGoodsType(userId, goods.getGoodsId(), goods.getGoodsType());
            int number = 0;
            for (SsMoneyOrderDetail ssMoneyOrderDetail : ssMoneyOrderDetails) {
                number += ssMoneyOrderDetail.getNumber();
            }
            if (number >= numberLimit) {
                throw new ServiceException("下单失败，原因：超过购买次数限制。");
            }
        }
    }


}
